#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <ctime>
#include <sys/types.h>
#include <sys/wait.h>
#include "ProcessPool.hpp"
using namespace std;

#define Process_Num 5//宏定义要创建的子进程数量
vector<pair<pid_t,int>> slots;
uint32_t receive_command(int readfd,bool *flag)
{
    uint32_t command = 0;
    ssize_t s = read(readfd,&command,sizeof(command));
    if(s == 0)
    {
        *flag = 0;
        return -1;
    }
    return command;
}

void push_and_wakeup(uint32_t sonnum,uint32_t missionnum)
{
    int ret = write(slots[sonnum].second,&missionnum,sizeof(missionnum));
    cout<<"父进程派发任务成功!派发进程序号["<<sonnum<<"],派发任务序号["<<missionnum<<"],子进程pid:"<<slots[sonnum].first<<endl;
}

int main()
{
    int count = 20;
    srand((unsigned int)time(nullptr));
    load();
    //show();
    for(int i = 0;i<Process_Num;i++)//for循环创建对应数量的子进程
    {
        int processfd[2] = {0};
        pipe(processfd);//创建对应子进程呃对应读写端 processfd[0]是读端 processfd[1]是写端
        int id = fork();
        if(id < 0)
        {
            perror("fork");
            exit(1);
        }
        if(id == 0)//子进程
        {
            
            close(processfd[1]);
            while(1)
            {
                bool flag = 1;
                uint32_t commandid = receive_command(processfd[0],&flag);
                //cout<<"---------------------------------"<<commandid<<' '<<flag<<endl;
                if(flag == 0)
                {
                    cout<<"我读到文件结尾了，我要退出了"<<endl;
                    //break;
                    exit(1);
                }
                if(commandid >=0 && commandid<= callbacks.size())
                {
                    callbacks[commandid]();
                }
            }
            //exit(1);//这个十分重要！！！！！！！！！ 子进程在做完自己的事情后一定要记得退出！！！！不然会坑到死
        }
        //父进程
        close(processfd[0]);
        slots.push_back({id,processfd[1]});
    }
    for(int i = 0;i<slots.size();i++)
    {
        cout<<slots[i].first<<' '<<slots[i].second<<endl;
    }
    while(count--)
    {
        uint32_t sonnum = rand() % slots.size();
        uint32_t missionnum = rand() % callbacks.size();
        push_and_wakeup(sonnum,missionnum);
        sleep(1);
    }
    for(auto e:slots)
    {
        close(e.second);
        cout<<"关闭fd成功"<<endl;
    }
    for(auto e:slots)
    {
        waitpid(e.first,nullptr,0);
        cout<<"回收僵尸进程成功"<<endl;
    }
    return 0;
}